#include "fd_manager.h"
#include "hook.h"
#include "log.h"

#include <cstdint>
#include <fcntl.h>
#include <mutex>
#include <shared_mutex>
#include <sys/stat.h>

//通过文件句柄构造FdCtx
FdCtx::FdCtx(int fd)
:m_isInit(false)
,m_isSocket(false)
,m_sysNonblock(false)
,m_userNonblock(false)
,m_isClosed(false)
,m_fd(fd)
,m_recvTimeout(UINT64_MAX)
,m_sendTimeout(UINT64_MAX) 
{
    init();
}

FdCtx::~FdCtx() {}

//初始化
bool FdCtx::init()
{
    if(m_isInit)
    {
        return true;
    }
    m_recvTimeout = UINT64_MAX;
    m_sendTimeout = UINT64_MAX;

    //获取对应文件描述符的文件状态信息 
    struct stat fd_stat;
    if(-1 == fstat(m_fd, &fd_stat)) //如果调用失败
    {
        m_isInit = false;
        m_isSocket = false;
    }
    else 
    {
        m_isInit = true;
        m_isSocket = S_ISSOCK(fd_stat.st_mode); //判断m_fd是否为socket类型
    }

    if(m_isSocket)
    {
        int flags = fcntl_f(m_fd, F_GETFL, 0);
        //如果不是非阻塞模式(不是异步)
        if(!(flags & O_NONBLOCK))
        {
            fcntl_f(m_fd, F_SETFL, flags | O_NONBLOCK);
            m_sysNonblock = true;
        }
    }
    else 
    {
        m_sysNonblock = false;
    }

    m_userNonblock = false;
    m_isClosed = false;

    return m_isInit;
}

//设置超时时间 SO_RCVTIMEO(读超时), SO_SNDTIMEO(写超时)
void FdCtx::setTimeout(int type, uint64_t v)    
{
    if(type == SO_RCVTIMEO)
    {
        m_recvTimeout = v;
    }
    else 
    {
        m_sendTimeout = v;
    }
}

//获取超时时间 SO_RCVTIMEO(读超时), SO_SNDTIMEO(写超时)
uint64_t FdCtx::getTimeout(int type)    
{
    if(type == SO_RCVTIMEO)
    {
        return m_recvTimeout;
    }

    return m_sendTimeout;
}

//========================================================================

FdManager::FdManager()
{
    m_fdDatas.resize(64);
}

//获取/创建文件句柄类FdCtx
FdCtx::ptr FdManager::get(int fd, bool auto_create)
{
    if(fd == -1)
    {
        log_error("FdManager::get fd = -1");
        return nullptr;
    }

    std::shared_lock<std::shared_mutex> read_lock(m_sharedMutex);
    if((int)m_fdDatas.size() <= fd)
    {
        if(auto_create == false)
        {
            log_warning("m_fdDatas.size(): {}, fd: {} - auto_create == false", m_fdDatas.size(), fd);
            return nullptr;
        }
    }
    else 
    {
        //如果fd已结初始化则直接返回已有fd
        //如果没有初始化fd并且不自动创建则返回nulls
        if(m_fdDatas[fd] || !auto_create)
        {
            // log_warning("m_fdDatas.size(): {}, fd: {} - am_fdDatas[fd] == nullptr,", m_fdDatas.size(), fd);
            return m_fdDatas[fd];
        }  
    }
    read_lock.unlock();

    //如果当前没有对应的fd,则新创建fd
    std::unique_lock<std::shared_mutex> write_lock(m_sharedMutex);
    FdCtx::ptr ctx(new FdCtx(fd));
    if(fd >= (int)m_fdDatas.size())
    {
        m_fdDatas.resize(fd * 1.5);
    }
    m_fdDatas[fd] = ctx;
    return ctx;
}

//删除对应文件描述符
void FdManager::del(int fd)
{
    std::unique_lock<std::shared_mutex> write_lock(m_sharedMutex);
    if((int)m_fdDatas.size() <= fd)
    {
        return;
    }
    m_fdDatas[fd].reset();
}